﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using BabyPoetryConference.Base;
using BabyPoetryConference.DbHelpers;
using BabyPoetryConference.Entities;
using BabyPoetryConference.Extensions;
using Microsoft.Extensions.Configuration;
using NLog;

namespace BabyPoetryConference.Services
{
    public class QuestionService : IQuestionService
    {
        private static readonly Logger _Logger = LogManager.GetCurrentClassLogger();
        public string Msg { get; set; }
        public string ErrMsg { get; set; }
        public List<string> QuestionSubject { get; set; } = new List<string>();
        private string poetry_file_name;
        private string question_file_name;
        private Dictionary<string, List<string>> author_dynasty_dict;
        private List<string> FlowerOrder;
        private Dictionary<string, List<string>> NewFlowerOrder;
        private List<string> _Idioms;
        public Dictionary<string, Poem> PoetryDict { get; set; } = new Dictionary<string, Poem>(); //诗词实体类集合，key为诗词名称便于查询
        private List<string> PoetryNameList = new List<string>(); //用于保存诗词名称保证诗词不重复
        private Dictionary<string, Question> _QuestionDict = new Dictionary<string, Question>(); //问题集合
        private List<string> _QuestionNoList = new List<string>(); //问题编号表保证诗词不重复

        private IConfiguration _Config;
        private PoetryDbHelperExcel _DbHelper;
        private Random _Random = new Random();
        public QuestionService(Config config, PoetryDbHelperExcel dbHelper)
        {
            _Config = config.Configuration;
            _DbHelper = dbHelper;
        }

        #region IService
        public void Start()
        {
            // 加载问题科目集合
            var files = _Config.GetSection("file").GetChildren();
            foreach (var fileItem in files)
            {
                if (fileItem.Value.Equals("yes", StringComparison.OrdinalIgnoreCase))
                {
                    QuestionSubject.Add(fileItem.Key);
                }
            }
            // 缩写文件名 后面看着清晰易懂
            poetry_file_name = Path.Combine(_Config.GetSection("path").GetString("poetry_file_path"), _Config.GetSection("poetry_file").GetString("poetry_file_name"));
            question_file_name = Path.Combine(_Config.GetSection("path").GetString("question_file_path"), _Config.GetSection("question_file").GetString("question_file_name"));
            // 加载诗词库
            _Logger.Info("加载诗词库");
            if (_Config.GetSection("file").GetBoolean("poetry_file"))
            {
                author_dynasty_dict = _DbHelper.GetAuthorDynasty();
                FlowerOrder = _DbHelper.GetFlowerOrder();
                NewFlowerOrder = _DbHelper.GetNewFlowerOrder();
                // 如果有根据成语获取诗句的题则加载成语库
                if (_Config.GetSection("question_type").GetBoolean("get_sentence_by_idiom"))
                {
                    _Idioms = _DbHelper.GetIdioms();
                }
                // 直接加载诗词库
                _DbHelper.GetPoetryStore(PoetryDict, PoetryNameList, author_dynasty_dict);

            }
            // 加载独立问题库
            if (_Config.GetSection("file").GetBoolean("question_file"))
            {
                _DbHelper.GetQuestionStore(_QuestionDict, _QuestionNoList);
            }
            // 写日志
            _Logger.Info("************************************************");
            _Logger.Info("又开始玩游戏了!");
        }

        public void Stop()
        {
        }
        #endregion

        #region IQuestionService
        public Question GetQuestion()
        {
            var rnd = _Random.Next(QuestionSubject.Count);
            var subject = QuestionSubject[rnd];
            _Logger.Info($"题目类型：{subject}");
            if (subject.Equals("question_file", StringComparison.OrdinalIgnoreCase))
            {
                return GetChinaQuestion();
            }
            if (subject.Equals("poetry_file", StringComparison.OrdinalIgnoreCase))
            {
                return GetPoetryQuestion();
            }
            _Logger.Error($"[{subject}]是个啥题目类型？");
            return null;

        }

        public List<Question> GetAllQuestionsOfAllPoems()
        {
            var allQuestions = new List<Question>();
            foreach(var poem in PoetryDict.Values)
            {
                var questions = GetAllQuestionsOfPoem(poem);
                allQuestions.AddRange(questions);
            }
            return allQuestions;
        }
        #endregion
        /// <summary>
        /// 获取独立问题
        /// </summary>
        /// <returns></returns>
        private Question GetChinaQuestion()
        {
            if (!_Config.GetSection("other").GetBoolean("question_isRepeat"))
            {
                if (_QuestionNoList.Count == 0)
                {
                    _QuestionNoList.AddRange(_QuestionDict.Keys);
                }
            }
            var currentCount = _QuestionNoList.Count;
            if(currentCount == 0)
            {

            }
            var rnd = _Random.Next(currentCount);
            var selectedQuestionNo = _QuestionNoList[rnd];
            var selectedQuestion = _QuestionDict[selectedQuestionNo];
            _Logger.Info($"这次选择的问题编号是:{selectedQuestionNo}");
            return selectedQuestion;
        }

        /// <summary>
        /// 获取诗词生成的问题
        /// </summary>
        /// <returns></returns>
        private Question GetPoetryQuestion()
        {
            var selectedPoetryName = "";
            // 诗词在每个循环内不重复
            if (!_Config.GetSection("other").GetBoolean("question_isRepeat"))
            {
                if (PoetryNameList.Count == 0)
                {
                    PoetryNameList.AddRange(PoetryDict.Keys);
                }
                var currentCount = PoetryNameList.Count;
                var rnd = _Random.Next(currentCount);
                selectedPoetryName = PoetryNameList[rnd];
            }
            else
            {
                var currentCount = PoetryDict.Keys.Count;
                var rnd = _Random.Next(currentCount);
                selectedPoetryName = PoetryDict.Keys.ToList()[rnd];
            }
            var selectedPoetry = PoetryDict[selectedPoetryName];
            var question = GenerateQuestionFromPoem(selectedPoetry);
            if (question == null)
            {
                question = GetPoetryQuestion();
            }
            return question;
        }

        /// <summary>
        /// 获取该诗词所有的问题
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private List<Question> GetAllQuestionsOfPoem(Poem poem)
        {
            var all = new List<Question>();
            // 加载[获取全诗内容（超过十句不加载）]题目
            var questionTypeList = get_question_type_list(poem);
            if (questionTypeList.Contains("get_content"))
            {
                var question = question_get_content(poem);
                question.BuildType = "get_content";
                question.Explain = poem.GetContent();
                all.Add(question);
            }
            // 加载[通过句子问题目和作者]题目
            if (questionTypeList.Contains("get_title_author_by_sentence"))
            {
                for(var i = 0; i < poem.Sentences.Count; i += 2)
                {
                    var question1 = new Question();
                    question1.No = poem.FullName;
                    question1.Content = $"请说出【{poem.Sentences[i]}】的下一句？";
                    question1.BuildType = "get_sentence";
                    question1.Answer = poem.Sentences[i + 1];
                    question1.Explain = poem.GetContent();
                    all.Add(question1);

                    var question2 = new Question();
                    question2.No = poem.FullName;
                    question2.Content = $"请说出【{poem.Sentences[i+1]}】的上一句？";
                    question2.BuildType = "get_sentence";
                    question2.Answer = poem.Sentences[i];
                    question2.Explain = poem.GetContent();
                    all.Add(question2);
                }
            }

            // 加载[句子填字]题目
            if (questionTypeList.Contains("get_fill_word"))
            {
                for (var i = 0; i < poem.Sentences.Count; i += 2)
                {
                    var sentences = $"{poem.Sentences[i]}{poem.Sentences[i + 1]}";
                    var sentencesCharArray = sentences.ToCharArray();
                    var excludeCharArray = new char[] { '，', '；', '。', '？', '！' };
                    var word_no = new List<int>();
                    while (word_no.Count < 4)
                    {
                        var rnd = _Random.Next(sentencesCharArray.Length);
                        if (word_no.Contains(rnd) || excludeCharArray.Contains(sentencesCharArray[rnd]))
                        {
                            continue;
                        }
                        word_no.Add(rnd);
                        sentencesCharArray[rnd] = '□';
                    }
                    var sentence_q = new string(sentencesCharArray);
                    word_no.Sort();
                    var words = new StringBuilder();
                    foreach (var j in word_no)
                    {
                        words.Append(sentences[j]).Append(" ");
                    }
                    var question = new Question
                    {
                        No = poem.FullName,
                        Content = $"填字：【{sentence_q}】",
                        Answer = $"{poem.FullName}\n{words.ToString().Substring(0, words.Length - 1)}",
                        BuildType = "get_fill_word",
                        Explain = poem.GetContent()
                    };
                    all.Add(question);
                }
            }
            // 加载[问诗词最前边两句]题目
            if (questionTypeList.Contains("get_head_sentence"))
            {
                var question = question_get_head_sentence(poem);
                question.BuildType = "get_head_sentence";
                question.Explain = poem.GetContent();
                all.Add(question);
            }

            // 加载[根据作者和部分字猜诗句]题目 等加入提示句之后再完成此功能
            if (questionTypeList.Contains("get_sentence_by_author_word"))
            {
            }

            // 加载[问诗句最后边两句]题目
            if (questionTypeList.Contains("get_last_sentence"))
            {
                var question = question_get_last_sentence(poem);
                question.BuildType = "get_last_sentence";
                question.Explain = poem.GetContent();
                all.Add(question);
            }

            // 加载[飞花令题目]题目
            if (questionTypeList.Contains("get_last_sentence"))
            {
                var questions = get_flower_orders_list(poem);
                foreach (var question in questions)
                {
                    question.BuildType = "get_sentence_by_flower_order";
                    question.Explain = poem.GetContent();
                    all.Add(question);
                }
            }

            // 加载[新飞花令题目]题目
            if (questionTypeList.Contains("get_sentence_by_new_flower_order"))
            {
                var questions = get_new_flower_orders_list(poem);
                foreach (var question in questions)
                {
                    question.BuildType = "get_sentence_by_new_flower_order";
                    question.Explain = poem.GetContent();
                    all.Add(question);
                }
            }

            // 加载[成语猜诗句题目]题目
            if (questionTypeList.Contains("get_sentence_by_idiom"))
            {
                var questions = get_idiom_list(poem);
                foreach (var question in questions)
                {
                    question.BuildType = "get_sentence_by_idiom";
                    question.Explain = poem.GetContent();
                    all.Add(question);
                }
            }
            return all;
        }

        private Question GenerateQuestionFromPoem(Poem poem)
        {
            var question = new Question();
            var questionTypeList = get_question_type_list(poem);
            if (questionTypeList.Count == 0)
            {
                return question;
            }
            var questionType = questionTypeList[_Random.Next(questionTypeList.Count)];
            switch (questionType)
            {
                case "get_content":
                    question = question_get_content(poem);
                    break;
                case "get_title_author_by_sentence":
                    question = question_get_title_author_by_sentence(poem);
                    break;
                case "get_sentence":
                    question = question_get_sentence(poem);
                    break;
                case "get_fill_word":
                    question = question_fill_word(poem);
                    break;
                case "get_head_sentence":
                    question = question_get_head_sentence(poem);
                    break;
                case "get_sentence_by_author_word":
                    question = question_get_sentence_by_author_word(poem);
                    break;
                case "get_last_sentence":
                    question = question_get_last_sentence(poem);
                    break;
                case "get_sentence_by_flower_order":
                    question = get_sentence_by_flower_order(poem);
                    break;
                case "get_sentence_by_new_flower_order":
                    question = get_sentence_by_new_flower_order(poem);
                    break;
                case "get_sentence_by_idiom":
                    question = get_sentence_by_idiom(poem);
                    break;
            }

            question.Subject = "poetry_content";
            question.Explain = getContent(poem);

            return question;
        }

        private string getContent(Poem poem)
        {
            var content = poem.FullName;
            var i = 1;
            foreach (var sentence in poem.Sentences)
            {
                i = i + 1;
                if (i % 2 == 0)
                {
                    content = $"{content}\n{sentence}";
                }
                else
                {
                    content = $"{content}{sentence}";
                }
            }
            return content;
        }

        /// <summary>
        /// 获取随机题目类型集合
        /// </summary>
        private List<string> get_question_type_list(Poem poem)
        {
            var ret = new List<string>();
            foreach (var child in _Config.GetSection("question_type").GetChildren())
            {
                if (child.Key.Equals("get_content"))
                {
                    if (child.Value.Equals("yes") && poem.Sentences.Count < 11)
                    {
                        ret.Add(child.Key);
                    }
                }
                else if (child.Key.Equals("get_sentence_by_flower_order"))
                {
                    if (child.Value.Equals("yes") && FlowerOrder.Count > 0)
                    {
                        ret.Add(child.Key);
                    }
                }
                else if (child.Key.Equals("get_sentence_by_new_flower_order"))
                {
                    if (child.Value.Equals("yes") && NewFlowerOrder.Count > 0)
                    {
                        ret.Add(child.Key);
                    }
                }
                else if (child.Key.Equals("get_sentence_by_idiom"))
                {
                    if (child.Value.Equals("yes") && _Idioms.Count > 0)
                    {
                        ret.Add(child.Key);
                    }
                }
                else
                {
                    if (child.Value.Equals("yes"))
                    {
                        ret.Add(child.Key);
                    }
                }
            }

            return ret;
        }
        /// <summary>
        /// 列出诗名和作者问全文
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private Question question_get_content(Poem poem)
        {
            var question = new Question();
            question.No = poem.FullName;
            question.Content = $"背诵{poem.FullName}";
            var contents = "";
            for (var i = 0; i < poem.Sentences.Count; i++)
            {
                if (i % 2 == 0)
                {
                    contents = $"{contents}{poem.Sentences[i]}";
                }
                else
                {
                    contents = $"{contents}{poem.Sentences[i]}\n";
                }
            }
            question.Answer = contents;
            return question;
        }

        /// <summary>
        /// 列出一句诗问诗名和作者
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private Question question_get_title_author_by_sentence(Poem poem)
        {
            var question = new Question();
            var two = get_two_sentence(poem);
            var sentences = "";
            foreach (var item in two.Values)
            {
                sentences = $"{sentences}{item}";
            }
            question.Content = $"【{sentences}】是哪个作者哪首诗中的句子？";
            question.Answer = poem.FullName;
            return question;
        }

        /// <summary>
        /// 随机获取诗中两句连续的句子
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private Dictionary<int, string> get_two_sentence(Poem poem)
        {
            var two = new Dictionary<int, string>();
            var sentence_no = _Random.Next(poem.Sentences.Count - 1);
            two.Add(sentence_no, poem.Sentences[sentence_no]);
            two.Add(sentence_no + 1, poem.Sentences[sentence_no + 1]);
            return two;
        }
        /// <summary>
        /// 列出一句诗问上句或者下句
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private Question question_get_sentence(Poem poem)
        {
            var question = new Question();
            var sentence_no = _Random.Next(poem.Sentences.Count);
            if (sentence_no % 2 == 0)
            {
                question.Content = $"【{poem.Sentences[sentence_no]}】的下一句是？";
                question.Answer = $"{poem.FullName}\n{poem.Sentences[sentence_no]}{poem.Sentences[sentence_no+1]}";
            }
            else
            {
                question.Content = $"【{poem.Sentences[sentence_no]}】的上一句是？";
                question.Answer = $"{poem.FullName}\n{poem.Sentences[sentence_no-1]}{poem.Sentences[sentence_no]}";
            }
            return question;
        }
        /// <summary>
        /// 列出两句诗填字
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private Question question_fill_word(Poem poem)
        {
            var question = new Question();
            question.No = poem.FullName;
            var two = get_two_sentence(poem);
            var sentences = "";
            foreach (var item in two.Values)
            {
                sentences = $"{sentences}{item}";
            }
            List<int> word_nos = new List<int>();
            while (word_nos.Count < 4)
            {
                var i = _Random.Next(poem.Sentences.Count);
                if (word_nos.Contains(i))
                {
                    continue;
                }
                word_nos.Add(i);
            }
            var charArray = sentences.ToCharArray();
            List<char> excludChars = new List<char> { '，', '。', '？', '！' };
            foreach (var i in word_nos)
            {
                var word_fill = charArray[i];
                if (!excludChars.Contains(word_fill))
                {
                    charArray[i] = '□';
                }
            }
            var sentences_q = new string(charArray);
            question.Content = $"填字：【{sentences_q}】";
            question.Answer = $"{poem.FullName}\n{sentences}";
            return question;
        }

        /// <summary>
        /// 给诗词名称作者问诗的前两句
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private Question question_get_head_sentence(Poem poem)
        {
            var question = new Question();
            question.No = poem.FullName;
            question.Content = $"背诵{poem.FullName}的前两句";
            question.Answer = $"{poem.Sentences[0]}{poem.Sentences[1]}";
            return question;
        }
        /// <summary>
        /// 给诗词名称和作者问诗的后两句
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private Question question_get_last_sentence(Poem poem)
        {
            var question = new Question();
            question.No = poem.FullName;
            question.Content = $"背诵{poem.FullName}的后两句";
            question.Answer = $"{poem.Sentences[poem.Sentences.Count - 2]}{poem.Sentences[poem.Sentences.Count - 1]}";
            return question;
        }
        /// <summary>
        /// 给出作者和诗句中的两个字问一句诗
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private Question question_get_sentence_by_author_word(Poem poem)
        {
            var question = new Question();
            var two = get_two_sentence(poem);
            var rnd = _Random.Next(two.Values.Count);
            var one = two.Values.ToArray()[rnd];
            var sentences = "";
            foreach (var item in two.Values)
            {
                sentences = $"{sentences}{item}";
            }
            var one_list = one.ToCharArray();
            var oneListCount = one_list.Length;
            List<char> excludChars = new List<char> { '，', '。', '？', '！' };
            int i, j = oneListCount;
            while (true)
            {
                i = _Random.Next(oneListCount);
                if (!excludChars.Contains(one_list[i]))
                {
                    break;
                }
            }
            if(oneListCount > 5)
            {
                while (true)
                {
                    j = _Random.Next(oneListCount);
                    if (!excludChars.Contains(one_list[j]) && j != i)
                    {
                        break;
                    }
                }
            }

            for(int n = 0; n < oneListCount; n++)
            {
                if(n == i)
                {
                    continue;
                }
                if(oneListCount > 5 && n == j)
                {
                    continue;
                }
                one_list[n] = '□';
            }
            var one_q = new string(one_list);
            question.Content = $"补全【{poem.Author}】的诗句：{one_q}";
            question.Answer = $"{poem.FullName}\n{sentences}";
            question.No = poem.FullName;
            return question;
        }
        
        private Question get_sentence_by_flower_order(Poem poem)
        {
            var question = new Question();
            var questions = get_flower_orders_list(poem);
            var rnd = _Random.Next(questions.Count);
            return questions[rnd];
        }
        private Question get_sentence_by_new_flower_order(Poem poem)
        {
            var question = new Question();
            var questions = get_new_flower_orders_list(poem);
            var rnd = _Random.Next(questions.Count);
            return questions[rnd];
        }
        private Question get_sentence_by_idiom(Poem poem)
        {
            var question = new Question();
            var questions = get_idiom_list(poem);
            if (questions.Count == 0)
                return question;
            var rnd = _Random.Next(questions.Count);
            return questions[rnd];
        }
        /// <summary>
        /// 获取飞花令题目集合
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private List<Question> get_flower_orders_list(Poem poem)
        {
            var questions_flower_order = new List<Question>();
            var question = new Question();
            foreach(var word in FlowerOrder)
            {
                var bool_sen = false;
                foreach(var sentence in poem.Sentences)
                {
                    if (sentence.Contains(word))
                    {
                        if (bool_sen)
                        {
                            question.Answer = $"{question.Answer}\n{sentence.Substring(0, sentence.Length-1)}";
                        }
                        else
                        {
                            question.No = poem.FullName;
                            bool_sen = true;
                            question.Content = $"请说出{poem.FullName}中带【{word}】字的任意一句";
                            question.Answer = sentence.Substring(0, sentence.Length - 1);
                        }
                    }
                }
                if (bool_sen && !string.IsNullOrEmpty(question.No))
                {
                    questions_flower_order.Add(question);
                }
            }
            return questions_flower_order;
        }
        /// <summary>
        /// 获取新飞花令题目集合
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private List<Question> get_new_flower_orders_list(Poem poem)
        {
            var questions_flower_order = new List<Question>();
            var question = new Question();
            foreach(var key in NewFlowerOrder.Keys)
            {
                var bool_sen = false;
                foreach (var sentence in poem.Sentences)
                {
                    foreach(var word in NewFlowerOrder[key])
                    {
                        if (sentence.Contains(word))
                        {
                            if (bool_sen)
                            {
                                if (!question.Answer.Contains(sentence.Substring(0, sentence.Length - 1)))
                                {
                                    question.Answer = $"{question.Answer}\n{sentence.Substring(0, sentence.Length - 1)}";
                                }
                                
                            }
                            else
                            {
                                question.No = poem.FullName;
                                bool_sen = true;
                                question.Content = $"请说出{poem.FullName}中带【{key}】字的一句";
                                question.Answer = sentence.Substring(0, sentence.Length - 1);
                            }
                        }
                    }
                    
                }
                if (bool_sen && !string.IsNullOrEmpty(question.No))
                {
                    questions_flower_order.Add(question);
                }
            }
            return questions_flower_order;
        }
        /// <summary>
        /// 获取成语组句题目集合
        /// </summary>
        /// <param name="poem"></param>
        /// <returns></returns>
        private List<Question> get_idiom_list(Poem poem)
        {
            var question_idiom = new List<Question>();
            foreach(var sentence in poem.Sentences)
            {
                var idiom_list = new List<string>();
                var new_sentence = sentence.Substring(0, sentence.Length - 1);
                foreach (var word in new_sentence) //将诗中每个字分解出来匹配成语
                {
                    var idioms_temp = new List<string>(); //存储可用于这一个字的成语
                    foreach (var idiom in _Idioms)
                    {
                        if(idiom.Contains(word) && !idioms_temp.Contains(idiom))
                        {
                            idioms_temp.Add(idiom);
                        }
                    }
                    if(idioms_temp.Count == 0)
                    {
                        continue;
                    }
                    else
                    {
                        var rnd = _Random.Next(idioms_temp.Count);
                        idiom_list.Add(idioms_temp[rnd]);
                    }
                }
                if(new_sentence.Length == idiom_list.Count)
                {
                    var question = new Question();
                    question.No = $"{poem.FullName}";
                    question.Content = "请从以下每条成语中选一个字组成一句诗（成语数量即这句诗的字数）";
                    if (_Config.GetSection("question_type_item").GetBoolean("get_sentence_by_idiom_random"))
                    {
                        while(idiom_list.Count >0)
                        {
                            var rnd = _Random.Next(idiom_list.Count);
                            var idiom = idiom_list[rnd];
                            question.Content = $"{question.Content}\n{idiom}";
                            idiom_list.RemoveAt(rnd);
                        }
                    }
                    else
                    {
                        for(var i = 0; i < idiom_list.Count; i++)
                        {
                            question.Content = $"{question.Content}\n{idiom_list[i]}";

                        }
                    }
                    question.Answer = new_sentence;
                    question_idiom.Add(question);
                }
            }
            return question_idiom;
        }
    }
}
